/*
MIT License 

Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов, 

https://bmstu.codes/lsx/simodo
*/

#ifndef simodo_token_LexicalParameters
#define simodo_token_LexicalParameters

/*! \file LexicalParameters.h
    \brief Параметры лексики
*/

#include "simodo/inout/token/Lexeme.h"

#include <vector>
#include <string>
#include <istream>
#include <cstdint>

namespace simodo::inout
{
    /*!
     * \brief Параметры лексемы с отметками начала и окончания
     *
     * Задаёт параметры лексемы с помеченным началом и концом (комментарии, строки и пр.)
     *
     * Структурный класс (не совершает никаких действий над хранимыми элементами).
     */

    struct MarkupSymbol
    {
        std::u16string  start;          ///< Символы начала строковой константы
        std::u16string  end;            ///< Символы конца строковой константы
        std::u16string  ignore_sign;    ///< Символы признака игнорирования управляющего символа
        LexemeType      type;           ///< Тип лексемы
    };

    typedef uint8_t     number_system_t;///< Система счисления

    /*!
     * \brief Числовая маска
     *
     * Структурный класс (не совершает никаких действий над хранимыми элементами).
     */
    struct NumberMask
    {
        std::u16string  chars;          ///< Маска числа
        LexemeType      type;           ///< Тип лексемы
        number_system_t system;         ///< Система счисления
    };

    inline const std::u16string  DIGITS            = u"0123456789ABCDEF";
                                                   ///< Циферки
    inline const std::u16string  LATIN_ALPHABET    = u"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
                                                   ///< Латинский алфавит (сначала нижний, затем верхний регистр!)
    inline const std::u16string  NATIONAL_ALPHABET = u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
                                                   ///< Буквы кириллицы (сначала нижний, затем верхний регистр!)
    inline const std::u16string  ID_EXTRA_SYMBOLS  = u"_";
                                                   ///< Дополнительные символы, допустимые для идентификаторов
    inline const std::u16string  BUILDING_NUMBER   = u"@BUILDING_NUMBER_MASK";
                                                   ///< Встроенная маска для целого и вещественного десятичного числа

    /*!
     * \brief Структура, определяющая набор параметров сканирования (настройки сканера)
     *
     * Определяет лексическую составляющую языка, по которой, в том числе, можно определить
     * принадлежность текста тому или иному языку.
     *
     * Структурный класс (не совершает никаких действий над хранимыми элементами).
     */

    struct LexicalParameters
    {
        // Группа параметров, определяемая извне:
        std::vector<MarkupSymbol>   markups     = {
            /// @note Пример заполнения полей:
            // {u"\"", u"\"", u"\\", LexemeType::Annotation},
        };                ///< Параметры символов с помеченным началом и концом (комментарии, строки и пр.)
        std::vector<NumberMask>     masks       = {
            /// @attention Строка с комбинированной маской числа (BUILDING_NUMBER) должна быть позже всех остальных
            /// более простых масок (например, 0xN), иначе остальные маски не будут срабатывать! Именно поэтому
            /// она закомментирована.
            //{ BUILDING_NUMBER, LexemeType::Number, 10 },
        }; ///< Числовая маска
        std::u16string              punctuation_chars;      ///< Символы пунктуации (односимвольные)
        std::vector<std::u16string> punctuation_words;      ///< Массив многосимвольных пунктуаций (в т.ч. ключевых слов)
        // Параметры для определения алфавита для числовых констант и наименований переменных, зависимая от кодировки:
        std::u16string  digits                  = DIGITS;
                                                            ///< Циферки
        std::u16string  latin_alphabet          = LATIN_ALPHABET;
                                                            ///< Латинский алфавит (сначала нижний, затем верхний регистр!)
        std::u16string  national_alphabet       = NATIONAL_ALPHABET;
                                                            ///< Буквы кириллицы (сначала нижний, затем верхний регистр!)
        std::u16string  id_extra_symbols        = ID_EXTRA_SYMBOLS;
                                                            ///< Дополнительные символы, допустимые для идентификаторов
        // Параметры, задающие лексическую семантику по умолчанию:
        bool        may_national_letters_use    = false;    ///< Признак допустимости применения национального алфавита
        bool        may_national_letters_mix    = false;    ///< Признак допустимости смешивания национального и латинского алфавитов
        bool        is_case_sensitive           = true;     ///< Признак чувствительности к регистру (для ключевых слов)
        std::u16string  eof_symbol              = u"";      ///< Строка (из набора пунктуаций), заменяющая конец файла
        std::u16string  nl_substitution         = u"";      ///< Строка (из набора пунктуаций), заменяющая конец строки
    };

}

#endif // simodo_token_LexicalParameters
